using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace MvvmFx.Common.Helpers
{
    /// <summary>
    /// An EnumHelper class designed to provide 
    /// helper methods related to Enum's.
    /// </summary>
    public static class EnumHelper
    {
        /// <summary>
        /// Convert a string value to an enum of type T
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static T Parse<T>(string value)
        {
            #region Argument Validation
            if (ReferenceEquals(value, null))
            {
                throw new ArgumentNullException("value");
            }
            #endregion

            if (!Enum.IsDefined(typeof(T), value))
            {
                throw new ArgumentOutOfRangeException("value",
                                                      string.Format("{0} Enum does not contain a value of '{1}'.",
                                                                    typeof(T).Name, value));
            }

            T e = (T)Enum.Parse(typeof(T), value, true);

            return e;
        }

        /// <summary>
        /// Convert a string value to an enum of type T
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool TryParse<T>(string value, out T result)
        {
            #region Argument Validation

            if (ReferenceEquals(value, null))
            {
                throw new ArgumentNullException("value");
            }

            #endregion

            if (!Enum.IsDefined(typeof(T), value))
            {
                result = default(T);
                return false;
            }

            result = (T)Enum.Parse(typeof(T), value, true);

            return true;
        }

        /// <summary>
        /// Get all the values for a given enum T.
        /// </summary>
        /// <typeparam name="T">The type of enum.</typeparam>
        /// <returns>The list of values for the enum T.</returns>
        public static List<T> GetEnumValues<T>()
        {
            Type enumType = typeof(T);
            List<T> enumValues = new List<T>();

            var fields = from field in enumType.GetFields()
                         where field.IsLiteral
                         select field;

            foreach (FieldInfo field in fields)
            {
                object value = field.GetValue(enumType);
                enumValues.Add((T)value);
            }

            return enumValues;
        }

        /// <summary>
        /// Get all the values for a given enum T.
        /// </summary>
        /// <typeparam name="T">The type of enum.</typeparam>
        /// <returns>The list of values for the enum T.</returns>
        public static List<string> GetEnumStrings<T>()
        {
            Type enumType = typeof(T);
            List<string> enumValues = new List<string>();

            var fields = from field in enumType.GetFields()
                         where field.IsLiteral
                         select field;

            foreach (FieldInfo field in fields)
            {
                object value = field.GetValue(enumType);
                enumValues.Add(value.ToString());
            }

            return enumValues;
        }

    }
}